#ifndef ____SSBASEL__SSBASE__BASE_SCOPED_REF_PTR__H__
#define ____SSBASEL__SSBASE__BASE_SCOPED_REF_PTR__H__

_SSL_BEGIN
_SSBASEL_BEGIN

template <class T>
class scoped_ref_ptr
{
public:
	scoped_ref_ptr() : ptr_(NULL)
	{

	}

	scoped_ref_ptr(T* p) : ptr_(p)
	{
		if (ptr_)
			ptr_->add_ref();
	}

	scoped_ref_ptr(const scoped_ref_ptr<T>& r) : ptr_(r.ptr_)
	{
		if (ptr_)
			ptr_->add_ref();
	}

	template <typename U>
	scoped_ref_ptr(const scoped_ref_ptr<U>& r) : ptr_(r.get())
	{
		if (ptr_)
			ptr_->add_ref();
	}

	~scoped_ref_ptr()
	{
		if (ptr_)
			ptr_->release();
	}

	T* get() const { return ptr_; }
	operator T*() const { return ptr_; }
	T* operator->() const
	{
		return ptr_;
	}

	T* release()
	{
		T* retVal = ptr_;
		ptr_ = NULL;
		return retVal;
	}

	scoped_ref_ptr<T>& assign_no_ref(T *p)
	{
		T* old_ptr = ptr_;
		ptr_ = p;
		if (old_ptr)
			old_ptr->release();
		return *this;
	}

	scoped_ref_ptr<T>& operator=(T* p)
	{
		// AddRef first so that self assignment should work
		if (p)
			p->add_ref();
		T* old_ptr = ptr_;
		ptr_ = p;
		if (old_ptr)
			old_ptr->release();
		return *this;
	}

	scoped_ref_ptr<T>& operator=(const scoped_ref_ptr<T>& r)
	{
		return *this = r.ptr_;
	}

	template <typename U>
	scoped_ref_ptr<T>& operator=(const scoped_ref_ptr<U>& r)
	{
		return *this = r.get();
	}

	void swap(T** pp)
	{
		T* p = ptr_;
		ptr_ = *pp;
		*pp = p;
	}

	void swap(scoped_ref_ptr<T>& r)
	{
		swap(&r.ptr_);
	}

protected:
	T* ptr_;
};

template <typename T>
scoped_ref_ptr<T> make_scoped_ref_ptr(T* t)
{
	return scoped_ref_ptr<T>(t);
}

_SSBASEL_END
_SSL_END


#endif
